package com.ruoyi.web.controller.rest;

import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.HttpInteractionUtil;
import com.ruoyi.system.domain.WebUser;
import com.ruoyi.system.service.IWebMallUserOrderService;
import com.ruoyi.system.service.IWebUserService;
import com.ruoyi.wechat.api.SharedImageUtils;
import com.ruoyi.wechat.api.WechatApi;
import com.ruoyi.wechat.api.WechatXcxApi;
import com.ruoyi.wechat.config.WechatConfig;
import com.ruoyi.wechat.config.WechatPayConfig;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信公众号菜单 信息操作处理
 *
 * @author liupan
 * @date 2019-03-25
 */
@Api(tags = "微信相关操作")
@RestController
@RequestMapping("/rest/wechat")
public class _WechatController extends BaseController {
    @Autowired
    private WechatConfig wechatConfig;

    @Autowired
    private IWebUserService iWebUserService;

    /**
     * 文件上传路径
     */
    public static final String UPLOAD_PATH = "/profile/upload/";

    @GetMapping("validateWechatServiceAddress")
    public String validateWechatServiceAddress(HttpServletRequest request) {
        String signature = request.getParameter("signature");// 微信加密签名，signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
        String timestamp = request.getParameter("timestamp");// 时间戳
        String nonce = request.getParameter("nonce");// 随机数
        if (StringUtils.isEmpty(nonce) || StringUtils.isEmpty(timestamp))
            return null;
        String echostr = request.getParameter("echostr");
        // PrintWriter out = response.getWriter();
        String result = WechatApi.validateServiceUrl(timestamp, nonce);
        logger.info(String.format("--微信返回信息:%s,%s,%s,%s，本地校验值:%s", signature, timestamp, nonce, echostr, result));
        if (result.equals(signature)) {
            return echostr;
        }
        return null;
    }

    /***
     * 登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程
     *
     * @return
     */
    @ApiOperation(value = "登录凭证校验", notes = "通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程,普通用户没有审核状态，回收员等身份有审核状态信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "js_code", value = "js_code", required = true),
            @ApiImplicitParam(name = "headPic", value = "头像"),
            @ApiImplicitParam(name = "recommendCode", value = "推荐码"),
    })
    @PostMapping()
    public AjaxResult code2Session(String js_code, String nickName, String headPic, String recommendCode, HttpServletRequest request) {
        if (StringUtils.isEmpty(js_code)) {
            return AjaxResult.error("js_code不能为null");
        }
        String result = WechatXcxApi.jscode2session(js_code);
        result = HttpInteractionUtil.getDate(result, "utf-8");
        JSONObject jsonObject = JSONObject.parseObject(result);
        String errcode = jsonObject.getString("errcode");
        if (StringUtils.isNotEmpty(errcode)) {
            //throw new BusinessException(jsonObject.getString("errmsg"));
            return AjaxResult.error(jsonObject.getString("errmsg"));
        }
        String openid = jsonObject.getString("openid");
        String session_key = jsonObject.getString("session_key");
//		if(openid == null){
//			openid = "111113";
//		}
        Map<String, Object> map = iWebUserService.saveRegisterUser(nickName, headPic, recommendCode, openid, request);
        map.put("session_key", session_key);
        return AjaxResult.success(map);
    }


    @ApiOperation(value = "用户的推广二维码")
    @GetMapping("getShareCode/{userId}")
    public AjaxResult getShareCode(@PathVariable Integer userId) {
        if (userId == null) {
            return error("userId不能为null");
        }

        WebUser userData = iWebUserService.getById(userId);
        if (userData == null) {
            return error(Constants.REQUIRED_FAILD);
        }
        try {
            // 小程序二维码
            String qrcode = RuoYiConfig.getShareQrcodePath();
            if (new File(qrcode).exists() == false) {
                File file = new File(qrcode);
                if (!file.exists()) {
                    file.mkdirs();
                }
            }
            qrcode = qrcode + "qrcode" + userData.getId() + ".png";
            if (new File(qrcode).exists() == false) {
                RestTemplate rest = new RestTemplate();
                String url = WechatXcxApi.getwxacodeunlimitUrl();
                Map<String, Object> param = new HashMap<>();
                param.put("scene", userData.getRecommCode());
                // param.put("page", "pages/Activity/Situation/Situation");
                param.put("width", 300);
                MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
                org.springframework.http.HttpEntity requestEntity = new org.springframework.http.HttpEntity(param, headers);
                ResponseEntity<byte[]> entity = rest.exchange(url, HttpMethod.POST, requestEntity, byte[].class);
                byte[] result = entity.getBody();
                InputStream inputStream = new ByteArrayInputStream(result);
                wirteFile(inputStream, qrcode);
            }

            // 背景图
            String url = wechatConfig.getDomain();

            String background = RuoYiConfig.getShareBackgroundPath();
            if (new File(background).exists() == false) {
                File file = new File(background);
                if (!file.exists()) {
                    file.mkdirs();
                }
            }
            background = background + "qinsitang_background.png";
            if (new File(background).exists() == false) {
                BufferedImage bufferedImage = SharedImageUtils.getRemoteBufferedImage(url + "/img/wechat/background.jpg");
                ImageIO.write(bufferedImage, "png", new File(background));
            }

            // 长按标识
            String point = RuoYiConfig.getShareBackgroundPath();
            if (new File(point).exists() == false) {
                File file = new File(point);
                if (!file.exists()) {
                    file.mkdirs();
                }
            }
            point = point + "point.png";
            if (new File(point).exists() == false) {
                BufferedImage bufferedImage = SharedImageUtils.getRemoteBufferedImage(url + "/img/wechat/point.png");
                ImageIO.write(bufferedImage, "jpg", new File(point));
            }

            // 头像
            if(StringUtils.isEmpty(userData.getHeadPic())){
                return error("未获取到用户头像，无法生存二维码");
            }
            BufferedImage headPic = SharedImageUtils.getRemoteBufferedImage(userData.getHeadPic());

            // 1. 通过背景图片构建 BufferedImage
            BufferedImage zoomPicture = ImageIO.read(new File(background));
            // 2. 头像裁剪成圆形
            BufferedImage roundedImage = SharedImageUtils.createRoundedImage(headPic, SharedImageUtils.AVATAR_SIZE);
            // 3. 合并头像，昵称
            BufferedImage mergeImage = SharedImageUtils.mergePicture(zoomPicture, roundedImage,
                    String.format("%s向您推荐%s系统",userData.getNickname(),RuoYiConfig.getName()));
            // 4. 合并二维码及二维码识别图
            mergeImage = SharedImageUtils.mergeQrcode(mergeImage, qrcode, point);

            File shareUserPath = new File(RuoYiConfig.getShareUserPath());
            if (shareUserPath.exists() == false) {
                shareUserPath.mkdirs();
            }

            shareUserPath = new File(shareUserPath.getPath() + "/qinsitang" + userData.getId() + ".png");
            //写入到本地文件
            // 5. 生成分享图
            ImageIO.write(mergeImage, "png", shareUserPath);

            return AjaxResult.success(wechatConfig.getDomain()+"profile/share/user/qinsitang" + userData.getId() + ".png");


        } catch (Exception e) {
            logger.error("调用小程序生成微信小程序码URL接口异常", e);
        }

        return error("生成失败");
    }

    private void wirteFile(InputStream is, String fileName) throws IOException {
        BufferedInputStream in = null;
        BufferedOutputStream out = null;
        in = new BufferedInputStream(is);
        out = new BufferedOutputStream(new FileOutputStream(fileName));
        int len = -1;
        byte[] b = new byte[1024];
        while ((len = in.read(b)) != -1) {
            out.write(b, 0, len);
        }
        in.close();
        out.close();
    }

    @RequestMapping("/washcarPaySuccessNotiry")
    public String washcarPaySuccessNotiry() throws Exception {
        String result = "false";
        InputStream inStream = getRequest().getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        String resultxml = new String(outSteam.toByteArray(), "utf-8");// 支付结果通知的xml格式数据
        if (StringUtils.isEmpty(resultxml))
            return result;

        logger.info("微信支付异步通知:" + resultxml);

        WechatPayConfig config = new WechatPayConfig(wechatConfig.getGzhAppId(),wechatConfig.getMch_id(),wechatConfig.getApi_key(),wechatConfig.getCertPath());
        WXPay wxpay = new WXPay(config);
        Map<String, String> notifyMap = WXPayUtil.xmlToMap(resultxml); // 转换成map

        if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
            // 签名正确
            // 进行处理。
            // 注意特殊情况：订单已经退款，但收到了支付结果成功的通知，不应把商户侧订单状态从退款改成支付成功
            String pay_no = notifyMap.get("out_trade_no");// 商户订单号

            String transaction_id = notifyMap.get("transaction_id"); // 微信交易号

            // String trade_type = notifyMap.get("trade_type");//交易类型
            // JSAPI、NATIVE、APP
            // 交易状态
            String result_code = notifyMap.get("result_code");// 业务结果
            // SUCCESS/FAIL

            // 用户在交易中支付的金额
            String buyer_pay_amount = notifyMap.get("total_fee");// 订单金额(分)
            double payMoney = new BigDecimal(buyer_pay_amount).divide(new BigDecimal("100")).doubleValue();

            iWebMallUserOrderService.paySuccess(pay_no, payMoney, transaction_id, result_code);
            result = "success";
        }

        return result;
    }

    @Autowired
    private IWebMallUserOrderService iWebMallUserOrderService;

}
